package com.jeasonzhao.commons.json;

import com.jeasonzhao.commons.parser.lex.LexException;
import com.jeasonzhao.commons.parser.lex.LexTokenCollection;

public class JSONArray extends JSONNode
{
    private static final long serialVersionUID = 1L;
    private java.util.Vector<JSONNode> m_subNodes = null;
    public JSONArray()
    {
        super(JSONNodeTypes.ARRAY);
    }

    public JSONArray(Object ...values)
    {
        this();
        this.setItems(values);
    }

    public JSONArray(java.lang.Iterable<?> objects)
    {
        this();
        if(null != objects)
        {
            for(Object obj : objects)
            {
                this.setItems(obj);
            }
        }
    }

    public JSONArray(java.util.Vector<JSONNode> colls)
    {
        super(JSONNodeTypes.ARRAY);
        m_subNodes = colls;
    }

    public JSONArray(LexTokenCollection tks)
        throws JSONException,LexException
    {
        super(JSONNodeTypes.ARRAY);
        setTokens(tks);
    }

    public final static JSONArray from(String str)
        throws JSONException,LexException
    {
        JSONNode node = JSONParser.parse(str);
        if(null == node || node.getNodeType() == JSONNodeTypes.ARRAY)
        {
            return(JSONArray) node;
        }
        else
        {
            throw new JSONException((JSONNode)null,"Could not convert the string to JSON array:" + str);
        }
    }

    public java.util.Vector<JSONNode> items()
    {
        return null == m_subNodes ? new java.util.Vector<JSONNode>() : m_subNodes;
    }

    public java.util.Vector<JSONClass> classItems()
    {
        if(null == this.m_subNodes || this.m_subNodes.size() < 1)
        {
            return new java.util.Vector<JSONClass>();
        }
        else
        {
            java.util.Vector<JSONClass> ret = new java.util.Vector<JSONClass>();
            for(JSONNode node : this.m_subNodes)
            {
                if(node!=null && node.isJSONClass())
                {
                    ret.add((JSONClass)node);
                }
            }
            return ret;
        }
    }

    public JSONArray setItems(Object ...nodes)
    {
        this.m_subNodes = null;
        return add(nodes);
    }

    public JSONArray add(Object ...nodes)
    {
        if(null == nodes)
        {
            return this;
        }
        for(Object obj : nodes)
        {
            if(null == obj)
            {
                continue;
            }
            if(null == m_subNodes)
            {
                m_subNodes = new java.util.Vector<JSONNode>();
            }
            m_subNodes.add(JSONNode.object2JSONNodeSafe(obj));
        }
        return this;
    }

    private void setTokens(LexTokenCollection tks)
        throws LexException,JSONException
    {
        this.m_tokens = tks;
        JSONParser p = new JSONParser(m_tokens.slice(1,m_tokens.size() - 1));
        JSONNode nodeFirst = p.next();
        m_subNodes = new java.util.Vector<JSONNode>();
        if(null == nodeFirst)
        {
            //throw new JSONException("????"+super.toString()+"???????????????????");
            return;
        }
        m_subNodes.add(nodeFirst);
//        System.out.println("              " + nodeFirst.getClass().getName() + " " + nodeFirst);
        while(true)
        {
            JSONNode node = p.next();
            if(node == null)
            {
                break;
            }
            if(node.m_nNodeType != JSONNodeTypes.SPECIAL)
            {
                throw new JSONException(this,node,"Wrong array delimiter \"" + node.toString() + "\".");
            }
            JSONSpecial specNode = (JSONSpecial) node;
            if(specNode.getValue() == null || specNode.getValue().equals(JSONParser.SPEC_ARRAY_DELIMETER) == false)
            {
                throw new JSONException(this,node,"Wrong array delimiter \"" + node.toString() + "\".");
            }
            node = p.next();
            if(null == node || node.m_nNodeType == JSONNodeTypes.NONE)
            {
                break;
            }
            if(node.m_nNodeType == JSONNodeTypes.ASSIGN)
            {
                throw new JSONException(this,node,"No assignment statment allowd in array\"" + node.toString() + "\"");
            }
            else if(node.m_nNodeType == JSONNodeTypes.SPECIAL)
            {
                throw new JSONException(this,node,"No special symbol allowed in array \"" + node.toString() + "\"");
            }
            else
            {
                m_subNodes.add(node);
            }
        }
    }

    public int size()
    {
        return null == m_subNodes ? 0 : m_subNodes.size();
    }

    public JSONNode getItem(int nIndex)
    {
        return null == m_subNodes ? null : m_subNodes.elementAt(nIndex);
    }

    public String toJSON(boolean isFullMode,int nLevel)
    {
        StringBuffer buf = new StringBuffer();
        buf.append(JSONParser.ARRAY_BEGIN);
        for(int n = 0;n < this.size();n++)
        {
            if(isFullMode)
            {
                buf.append("\r\n" + this.getPrefixSpace(nLevel));
            }
            if(n > 0)
            {
                buf.append(JSONParser.SPEC_ARRAY_DELIMETER);
            }
            buf.append(this.getItem(n)
                       .setJavaScriptCompatible(this.javaScriptCompatible)
                       .toJSON(false,nLevel + 1)); //isFullMode
        }
        if(isFullMode)
        {
            buf.append("\r\n" + getPrefixSpace(nLevel));
        }
        buf.append(JSONParser.ARRAY_END);
        return buf.toString();
    }
    public static final JSONArray create(){
        return new JSONArray();
    }

}
